package com.znxs.api_management_c.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.znxs.api_management_c.common.ErrorCode;
import com.znxs.api_management_c.exception.BusinessException;
import com.znxs.api_management_c.model.entity.UserInfo;
import com.znxs.api_management_c.service.UserInfoService;
import com.znxs.api_management_c.mapper.UserInfoMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.znxs.api_management_c.contant.userContant.USER_LOGIN_STATE;

/**
 * @author znxs
 * @description 针对表【user_info】的数据库操作Service实现
 * @createDate 2024-07-03 14:28:00
 */
@Slf4j
@Service
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo>
        implements UserInfoService {

    @Resource
    private UserInfoMapper userInfoMapper;

    // 用于密码加密
    private static final String SALT = "znxs";

    @Override
    public long userRegister(String username, String password, String checkPassword) {
        // 判断是否为空
        if (StringUtils.isAnyBlank(username, password, checkPassword))
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        // 判断是否符合格式
        {
            if (username.length() < 3 || username.length() > 8)
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "账号长度不能小于3位大于8位");
            if (password.length() < 6 || password.length() > 16)
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "密码长度不能小于6位大于16位");
            // 账户不能包含特殊字符
            String validPattern = "[`~!@#$%^&*()+=|{}':;',\\[\\].<>/?~！@#￥%……&*（）——+|{}【】‘；：”“’。，、？]";
            Matcher matcher = Pattern.compile(validPattern).matcher(username);
            if (matcher.find()) throw new BusinessException(ErrorCode.PARAMS_ERROR,"账户不能包含特殊字符");
            // 密码和校验密码必须相同
            if (!password.equals(checkPassword)) throw new BusinessException(ErrorCode.PARAMS_ERROR,"第二次密码必须与第一次密码相同");
        }
        // 用户名不能与账户用户名重复  【这一步是查询数据库，能放到后面就放到后面】
        QueryWrapper<UserInfo> userInfoQueryWrapper = new QueryWrapper<>();
        userInfoQueryWrapper.eq("name",username);
        Long one = userInfoMapper.selectCount(userInfoQueryWrapper);
        if (one>0) throw new BusinessException(ErrorCode.PARAMS_ERROR,"该用户名注册过了");
        // 密码加密 这里使用md5加密
        String encryptPassword = DigestUtils.md5DigestAsHex((SALT+username+password).getBytes());
        //插入数据
        UserInfo userInfo = new UserInfo();
        userInfo.setName(username);
        userInfo.setPassword(encryptPassword);
        boolean isSave = false;
        try {
            isSave = this.save(userInfo);
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR);
        }
        if (!isSave) return-1;
        return userInfo.getId();
    }

    @Override
    public UserInfo userLogin(HttpServletRequest request, String username, String password) {
        // 非空判断
        if (StringUtils.isAnyBlank(username,password)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"请求参数为空");
        }
        // 判断是否符合格式
        {
            if (username.length() < 3 || username.length() > 8)
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "账号长度不能小于3位大于8位");
            if (password.length() < 6 || password.length() > 16)
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "密码长度不能小于6位大于16位");
            // 账户不能包含特殊字符
            String validPattern = "[`~!@#$%^&*()+=|{}':;',\\[\\].<>/?~！@#￥%……&*（）——+|{}【】‘；：”“’。，、？]";
            Matcher matcher = Pattern.compile(validPattern).matcher(username);
            if (matcher.find()) throw new BusinessException(ErrorCode.PARAMS_ERROR,"账户不能包含特殊字符");
        }
        // 查询用户是否存在
        QueryWrapper<UserInfo> userInfoQueryWrapper = new QueryWrapper<>();
        userInfoQueryWrapper.eq("name",username);
        Long one = userInfoMapper.selectCount(userInfoQueryWrapper);
        if (one<1) throw new BusinessException(ErrorCode.PARAMS_ERROR,"用户不存在");
        // 密码加密
        String encryptPassword = DigestUtils.md5DigestAsHex((SALT +username+ password).getBytes());
        // 查询用户名密码是否正确
        userInfoQueryWrapper.eq("password",encryptPassword);
        log.info(encryptPassword);
        UserInfo userInfo = userInfoMapper.selectOne(userInfoQueryWrapper);
        if (userInfo == null){
            log.info("user login failed ,userAccount cannot match userPassword");
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR,"用户名或密码错误");
        }
        // 若用户存在，用户脱敏
        UserInfo safetyUser = getSafetyUser(userInfo);
        // 记录用户的登录态
        request.getSession().setAttribute(USER_LOGIN_STATE,safetyUser);
        return safetyUser;
    }

    @Override
    public boolean exitLogin(HttpServletRequest request) {
        // 删除登录态
        request.getSession().removeAttribute(USER_LOGIN_STATE);
        return false;
    }



    @Override
    public UserInfo getSafetyUser(UserInfo oldUserInfo) {
        UserInfo safeUserInfo = new UserInfo();
        safeUserInfo.setId(oldUserInfo.getId());
        safeUserInfo.setName(oldUserInfo.getName());
        safeUserInfo.setNickname(oldUserInfo.getNickname());
        safeUserInfo.setTelephone(oldUserInfo.getTelephone());
        safeUserInfo.setGender(oldUserInfo.getGender());
        safeUserInfo.setAvatarUrl(oldUserInfo.getAvatarUrl());
        safeUserInfo.setUserRole(oldUserInfo.getUserRole());
        safeUserInfo.setProfile(oldUserInfo.getProfile());
        safeUserInfo.setCreateTime(oldUserInfo.getCreateTime());
        return safeUserInfo;
    }



    @Override
    public boolean isLogin(HttpServletRequest request){
        // 获取登录时存入的session
        Object userInfo = request.getSession().getAttribute(USER_LOGIN_STATE);
        // 如果不为空，则判断已经登录
        return userInfo!=null;
    }




}




